'''
Created on Aug 30, 2009

@author: mkiyer
'''

import numpy as np
cimport numpy as np
cimport cython

# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info object.
DTYPE = np.float

# "ctypedef" assigns a corresponding compile-time type to DTYPE_t. For
# every type in the numpy module there's a corresponding compile-time
# type with a _t-suffix.
ctypedef np.float_t DTYPE_t

@cython.boundscheck(False) # turn of bounds-checking for entire function
def sliding_window2(np.ndarray[DTYPE_t, ndim=2] dsets, int wsize):
    assert dsets.dtype == DTYPE
    # allocate sliding window arrays
    cdef int chunk_size = dsets.shape[0] - wsize
    cdef int num_samples = dsets.shape[1]
    cdef np.ndarray[DTYPE_t, ndim=2] windows = np.empty((chunk_size, num_samples), dtype=DTYPE)
    # compute initial windows for beginning of bin
    windows[0] = np.sum(dsets[0:wsize], axis=0)
    # slide windows across entire bin
    cdef Py_ssize_t i
    for i in xrange(1, chunk_size):
        windows[i] = windows[i-1] - dsets[i-1] + dsets[i-1+wsize]
    # get rid of floating point precision errors
    windows = np.fabs(np.around(windows, 6))
    return windows
           
def sliding_window1(np.ndarray dsets, int wsize):
    assert dsets.dtype == DTYPE

    # allocate sliding window arrays
    cdef int chunk_size = dsets.shape[0] - wsize
    cdef int num_samples = dsets.shape[1]
    cdef np.ndarray windows = np.empty((chunk_size, num_samples), dtype=DTYPE)
        
    # compute initial windows for beginning of bin
    windows[0] = np.sum(dsets[0:wsize], axis=0)
    
    # slide windows across entire bin
    cdef Py_ssize_t j
    for j in xrange(1, chunk_size):
        windows[j] = windows[j-1] - dsets[j-1] + dsets[j-1+wsize]
    
    return windows

def naive_sliding_window(np.ndarray dsets, int wsize):
    # allocate sliding window arrays
    chunk_size = dsets.shape[0] - wsize
    windows = np.empty((chunk_size, dsets.shape[1]), dtype=dsets.dtype)
    # compute initial windows for beginning of bin
    windows[0] = np.sum(dsets[0:wsize], axis=0)
    # slide windows across entire bin
    for j in xrange(1, chunk_size):
        windows[j] = windows[j-1] - dsets[j-1] + dsets[j-1+wsize]
    return windows
